package Service

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/bwmarrin/snowflake"
	"github.com/jinzhu/copier"
	"gopkg.in/ini.v1"
	"log"
	"net/http"
	"strings"
	"web_back_go/Common/PayType"
	"web_back_go/DAO/gorm"
	"web_back_go/DAO/gorm/GormModel"
	"web_back_go/Dto"
	"web_back_go/Util"
)

/*
Pay
@Description: 不同的订单号，同一个支付流水号
*/
func Pay(userId string, payParam Dto.PayParam) Dto.PayInfoDto {
	db := gorm.Db.Begin()
	// 事务
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()
		}
		db.Commit()
	}()
	// 不同的订单号的产品名称
	var prodName strings.Builder
	// 支付单号
	// 使用雪花算法生成的支付单号
	node, _ := snowflake.NewNode(1) // 节点 ID=1
	id := node.Generate()
	var payNo = id.String()
	var orderNumbers []string = strings.Split(payParam.OrderNumbers, ",")
	// 修改订单信息
	for _, orderNumber := range orderNumbers {
		var orderSettlement GormModel.TzOrderSettlement
		orderSettlement.PayNo = &payNo
		orderSettlement.PayType = &payParam.PayType
		orderSettlement.UserID = &userId
		orderSettlement.OrderNumber = &orderNumber
		// 创建更新字段的 map
		updateFields := make(map[string]interface{})

		// 动态添加需要更新的字段
		if orderSettlement.PayNo != nil {
			updateFields["pay_no"] = *orderSettlement.PayNo
		}
		if orderSettlement.PayType != nil {
			updateFields["pay_type"] = *orderSettlement.PayType
		}
		if orderSettlement.IsClearing != nil {
			updateFields["is_clearing"] = *orderSettlement.IsClearing
		}
		if orderSettlement.ClearingTime != nil {
			updateFields["clearing_time"] = *orderSettlement.ClearingTime
		}

		// 执行更新操作
		db.Model(&GormModel.TzOrderSettlement{}).
			Where("order_number = ? AND user_id = ?", orderSettlement.OrderNumber, orderSettlement.UserID).
			Updates(updateFields)
		var order GormModel.TzOrder
		db.Where("order_number = ?", orderNumber).First(&order)
		prodName.WriteString(order.ProdName)
		prodName.WriteString(",")
	}
	// 除了ordernumber不一样，其他都一样
	var settlements []GormModel.TzOrderSettlement
	db.Where("pay_no =?", payNo).Find(&settlements)
	// 应支付的总金额
	payAmount := 0.0
	for _, orderSettlement := range settlements {
		payAmount = payAmount + *orderSettlement.PayAmount
	}
	//   prodName.substring(0, Math.min(100, prodName.length() - 1));
	var substringBuilder *strings.Builder = Util.SafeSubstring(&prodName, 100)
	var payInfoDto Dto.PayInfoDto
	payInfoDto.Body = substringBuilder.String()
	payInfoDto.PayAmount = payAmount
	payInfoDto.PayNo = payNo
	return payInfoDto
}

// PaySuccess 支付服务成功
func PaySuccess(payNo string, bizPayNo string) (paySuccess []string) {
	db := gorm.Db.Begin()
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()
		}
		db.Commit()
	}()
	var orderSettlements []GormModel.TzOrderSettlement
	db.Where("pay_no =?", payNo).Find(&orderSettlements)
	var settlement GormModel.TzOrderSettlement = orderSettlements[0]
	// 订单已支付
	if *settlement.PayStatus == 1 {
		panic("订单已支付")
	}
	// 修改订单结算信息
	//update tz_order_settlement set pay_status = 1, version = version +1 where pay_no = #{payNo} and version = #{version}
	if db.Model(&GormModel.TzOrderSettlement{}).Where("pay_no = ? AND version = ?", payNo, settlement.Version).
		Updates(map[string]interface{}{"pay_status": 1, "version": *settlement.Version + 1}).RowsAffected < 1 {
		panic("结算信息已更改")
	}
	// 提取 orderNumber 字段到新的切片
	var orderNumbers []string = make([]string, 0, len(orderSettlements))
	for _, settlement := range orderSettlements {
		orderNumbers = append(orderNumbers, *settlement.OrderNumber)
	}
	// 将订单改为已支付状态
	/*
	 <update id="updateByToPaySuccess">
	    update tz_order set status = 2,is_payed =1,update_time=NOW(),pay_time=NOW(),pay_type =#{payType} where order_number in
	    <foreach collection="orderNumbers" item="orderNumber" separator="," open="(" close=")">
	        #{orderNumber}
	    </foreach>
	  </update>
	*/
	// 构建 IN 条件部分
	placeholders := make([]string, len(orderNumbers))
	for i := range orderNumbers {
		placeholders[i] = "?"
	}
	inClause := "(" + strings.Join(placeholders, ",") + ")"

	// 构建完整的 SQL 语句
	sql := fmt.Sprintf(`
       UPDATE tz_order
       SET status = 2,
           is_payed = 1,
           update_time = NOW(),
           pay_time = NOW(),
           pay_type = ?
       WHERE order_number IN %s`, inClause)

	// 构建参数切片，先添加 payType，再添加 orderNumbers
	args := make([]interface{}, 0, len(orderNumbers)+1)
	//args = append(args, PayType.WECHATPAY.Value())
	args = append(args, PayType.ALIPAY.Value())
	for _, orderNumber := range orderNumbers {
		args = append(args, orderNumber)
	}

	// 执行 SQL 语句
	db.Exec(sql, args...)

	var orders []GormModel.TzOrder
	//向区块链发送订单信息
	cfg, _ := ini.Load("./Config/config.ini")
	enabled := cfg.Section("blockchain").Key("enabled").String()
	for _, number := range orderNumbers {
		var tmpOrder GormModel.TzOrder
		db.Where("order_number =?", number).First(&tmpOrder)
		var tmpOrderAsset Dto.OrderAsset
		err := copier.CopyWithOption(&tmpOrderAsset, &tmpOrder, copier.Option{IgnoreEmpty: true, DeepCopy: true})
		if err != nil {
			panic(err)
		}
		//值引用而不是对比内存地址
		//if *tmpOrder.IsPayed == 1 {
		//	tmpOrderAsset.IsPayed = true
		//} else {
		//	tmpOrderAsset.IsPayed = false
		//}
		//默认支付成功
		tmpOrderAsset.IsPayed = true
		jsonData, err := json.Marshal(tmpOrderAsset)
		url := cfg.Section("blockchain").Key("url").String()
		log.Println("发送数据", string(jsonData))
		log.Println("发送地址", url+"/CreateAsset")
		if enabled == "true" {
			go func() {
				resp, err := http.Post(url+"/CreateAsset", "application/json", bytes.NewBuffer(jsonData))
				if err != nil {
					log.Println("发送失败", err)
					return
				}
				defer resp.Body.Close()
			}()
		}
		orders = append(orders, tmpOrder)

	}
	return orderNumbers
}
